# -*- coding: utf-8 -*-
# @Time: 2021/8/21 23:35
# @Author: yuan hao
# @Remark: 视频管理db层
import logging
import time
from typing import List

from mxsoftpy import DB
from mxsoftpy.exception import DBError, ParamsError, DataError

from db.common.VideoManage.VideoQuality.inspection_task import InspectionTaskDB
from db.common.VideoManage.VideoQuality.video_group import VideoGroupDB
from server.common.VideoManage.VideoQuality.video_type import VideoUrl


class VideoDB(DB):

    def __video_name_duplicate_check(self, name: str, code: str = None):
        """
        校验分组名称是否重复
        """
        tree = self.tree.open('VideoQuality', 'Video', file='IOT')
        _, res_list = tree.filter(name=name, state=1)
        if res_list and res_list[0] != code:
            logging.error('新增视频时：校验name是否合法时发生重名')
            raise ParamsError(f"视频名称已存在")

    def create(self, **kwargs) -> str:
        """
        新增视频
        """
        video_group_list = VideoGroupDB().use_keys()

        if str(kwargs['group_code']) not in video_group_list:
            logging.error('新增视频时：校验group_code是否合法时发生错误：该group_code：%s不在用，在用视频组列表：%s' % (
                kwargs['group_code'], str(video_group_list)))
            raise DataError('错误的视频组code，该组不存在或已删除')
        self.__video_name_duplicate_check(kwargs['name'])
        try:
            code = self.tree.insert_key_items(kwargs)
            logging.info('新增了一个视频，视频code：%s，视频内容如下：' % code)
            logging.info(str(kwargs))
        except DBError:
            logging.error('新增视频出错,视频内容如下%s' % str(kwargs))
            raise DataError('新增视频出错,视频内容如下%s' % str(kwargs))

        return code

    def excel_create(self, **kwargs) -> str:
        """
        批量新增视频
        """
        self.__video_name_duplicate_check(kwargs['name'])
        try:
            code = self.tree.insert_key_items(kwargs)
            logging.info('新增了一个视频，视频code：%s，视频内容如下：' % code)
            logging.info(str(kwargs))
        except DBError:
            logging.error('新增视频出错,视频内容如下%s' % str(kwargs))
            raise DataError('新增视频出错,视频内容如下%s' % str(kwargs))

        return code

    def delete(self, del_list: list) -> list:
        """
        删除视频
        :param del_list: 要删除的video_code列表
        """
        for del_key in del_list:
            try:
                self.tree.open('VideoQuality', 'Video\\%s' % del_key, file='IOT')
            except DBError as e:
                raise DataError('批量删除视频时：打开视频code：%s时发生错误，错误信息：%s' % (del_key, str(e)))
            self.tree.insert_items([('state', 0), ('update_time', int(time.time()))])
            logging.info('删除了一个视频，视频code：%s' % del_key)
        return del_list

    def relevance_delete(self, video_code: str, plan_list: list, task_list: list):
        """
        将视频关联任务/计划 删除/停用
        """
        # self.tree.begin()
        # todo 开启事务
        try:
            for task in task_list:
                InspectionTaskDB().delete(task)
            for plan in plan_list:
                self.tree.open('VideoQuality', 'InspectionPlan\\%s' % plan, file='IOT')
                res_dict = self.tree.items(prop_list=['name', 'videos'])
                video_list = res_dict['videos'].split(';')
                video_list.remove(video_code)
                videos = ';'.join(video_list)
                data_state = 1 if videos else 0
                self.tree.insert_items([('videos', videos), ('data_state', data_state), ('update_time', int(time.time()))])
            # self.tree.commit()
            logging.info(f'视频code:{video_code}关联任务和计划已停用')
        except DBError:
            # self.tree.rollback()
            logging.error(f'视频code:{video_code}关联任务和计划停用失败')
            raise DBError(0, f'视频code:{video_code}关联任务和计划停用失败')
        return video_code

    def simple_list(self, keys: list = None, is_all: bool = False, **kwargs) -> dict:
        """
        返回符合条件的在用的视频
        params: keys : 视频code
        params: is_all : true为查所有 false查未删除
        """
        self.tree.open('VideoQuality', 'Video', file='IOT')
        if not keys:
            if is_all:
                _, keys = self.tree.filter(**kwargs)
            else:
                _, keys = self.tree.filter(state=1, **kwargs)
        return self.tree.sub_items(key_list=keys) if keys else dict()

    def select(self, **kwargs) -> tuple:
        """
        获取视频列表并分页
        """
        total, keys = self.tree.open('VideoQuality', 'Video', file='IOT').filter(**kwargs)
        sub_items = self.tree.sub_items(key_list=keys,
                                        prop_list=['name', 'username', 'password', 'device_ip', 'server_ip', 'aisle', 'stream_code',
                                                   'port', 'url', 'data_state', 'vendor', 'group_code']) if keys else {}
        res = dict()
        res['data'] = list()
        for key, video_info in sub_items.items():  # 保持排序、以及添加字段
            video_info['video_url'] = VideoUrl().url('HIKVISION', info=video_info)
            video_info.update({'video_code': key})
            res['data'].append(sub_items[key])

        return total, res

    def group_select(self,**kwargs) -> list:
        """分组获取视频"""
        total, keys = self.tree.open('VideoQuality', 'Video', file='IOT').filter(**kwargs)
        sub_items = self.tree.sub_items(key_list=keys,
                                        prop_list=['name', 'group_code', 'vendor', 'repair_state']) if keys else {}

        res_list = list()
        for key in keys:  # 保持排序、以及添加字段
            sub_items[key].update({'code': key, 'parent_code': sub_items[key].pop('group_code'), 'v_type': 1})
            res_list.append(sub_items[key])

        return res_list

    def retrieve(self, video_code: str) -> dict:
        """
        获取视频详情
        """
        try:
            self.tree.open('VideoQuality', 'Video\\%s' % video_code, file='IOT')
        except DBError as e:
            logging.error('打开视频详情时失败，视频code：%s，错误信息：%s' % (video_code, str(e)))
            raise ParamsError('获取视频详情失败')

        return self.tree.items()

    def update(self, video_code: str, **kwargs) -> str:
        """
        更新视频
        :param video_code: 视频code
        """
        self.__video_name_duplicate_check(kwargs['name'],video_code)
        try:
            self.tree.open('VideoQuality', 'Video\\%s' % video_code, file='IOT')
        except DBError as e:
            logging.error('更新视频时：打开视频code：%s失败，错误信息：%s' % (video_code, str(e)))
            raise DataError('更新视频失败')
        self.tree.insert_items(kwargs)
        logging.info('更新了一个视频, 视频code: %s, 更新内容如下: ' % video_code)
        logging.info(str(kwargs))
        return video_code

    def task_update(self,video_code: str, **kwargs) -> str:
        """
        执行任务时更新视频
        :param video_code: 视频code
        """
        try:
            self.tree.open('VideoQuality', 'Video\\%s' % video_code, file='IOT')
        except DBError as e:
            logging.error('更新视频时：打开视频code：%s失败，错误信息：%s' % (video_code, str(e)))
            raise DataError('更新视频失败')
        self.tree.insert_items(kwargs)
        logging.info('更新了一个视频, 视频code: %s, 更新内容如下: ' % video_code)
        logging.info(str(kwargs))
        return video_code

    def move(self, video_list: List[str], group_code: str) -> List[str]:
        """
        移动视频
        :param video_list: 视频code列表
        :param group_code: 新的分组code
        """

        if group_code == '0':
            raise DataError('不可移动至全部分组')

        for video in video_list:
            try:
                self.tree.open('VideoQuality', 'Video\\%s' % video, file='IOT').insert_item('group_code', group_code)
                logging.info('移动了一个视频，视频code：%s, 移动到了分组：%s' % (video, group_code))
            except DBError as e:
                logging.error('移动视频时发生错误, 视频code: %s，错误原因：%s' % (video, str(e)))
                raise DataError('移动视频时候发送错误，移动已停止')

        return video_list

